<?php
include_once ("dblib.php");

/**
 * The purpose of this class is to handle the values of elements  on our structure for being able to store nodes correctly.
 * @author CEPAL.
 * @package DataHandler
 */
class DataHandler {

    private $separador;
    private $separadorIds;
    private $nombreRaiz;
    private $tableName;
    private $nodoInterno;
    private $nodoElemento;


    /**
     * Parameters constructor
     * @param string $nombreTabla
     * @param array $parametros associative array of string:
     *  ['rel_char']
     *  ['id_char']
     *  ['tree_char']
     *  ['root_name']
     * @param bool $debug true for debug messages
     */
    function __construct($nombreTabla,$parametros,$debug=false){
        $this->separador=$parametros['separator'];
        $this->separadorIds=$parametros['id_char'];
        $this->nombreRaiz=$parametros['root_name'];
        $this->tableName=$nombreTabla;
        $this->nodoInterno=$parametros['internal_nodes_type_name'];
        $this->nodoElemento=$parametros['element_nodes_type_name'];
        if($debug){
            $mensaje="->TableName:$nombreTabla.<> RelSep: $this->separador.<>
            IdsSep: $this->separadorIds. <>TreeSep: $this->separador. <>Root: $this->nombreRaiz.<-";
            trigger_error($mensaje,E_USER_NOTICE);
        }
    }

    
    /**
     * This function returns the database table's name.
     * @return string
     */
    public function getTableName(){
        return $this->tableName;
    }


     /**
      * This function returns the value of a node with a known path.
      * @param string $path Path of the node to return.
      * @param ElementHandler $ehObject.
      * @param StructHandler $shObject.
      * @param bool $debug true for debug messages.
      * @return string Value of the node returned.
      */
    public function getValue($path,$ehObject,$shObject,$rhObject,$debug=false){
        if($debug){$mensaje=array();}
        $tablaDatos=$this->tableName;
        $params=$this->parsePath($path,$ehObject,$shObject,$rhObject,$debug);
        if($params==NULL) {
            if($debug){$mensaje[]="Invalid path: $path. Function will return NULL";}
            $resultado= NULL;
        }else{
            $query="SELECT value FROM ".$tablaDatos. " as td WHERE td.id=".$params['id']." AND td.id_structure=".$params['id_structure'];
            $result=DB::query($query);
            if(DB::num_rows($result)!=0) {
                $row=DB::fetch_assoc($result);
                if($debug){$mensaje[]="Found path: $path = ".$row['value'];}
                $resultado=$row['value'];
            }else{
                if($debug){$mensaje[]="Attribute doesn't exist in database: $path. Function will return NULL";}
                $resultado= NULL;
            }
        }
        if($debug){
            foreach($mensaje as $mens){
                trigger_error($mens,E_USER_NOTICE);
            }
        }
         return $resultado;
    }


    /**
     * @param string $path Path of the node to set the attribute
     * @param mixed $value Value to write.
     * @param ElementHandler $ehObject
     * @param StructHandler $shObject
     * @param bool $debug true for debug messages.
     * @return bool It returns true if the value has been written.
     */
    public function setValue($path,$value,$ehObject,$shObject,$rhObject,$debug=false){
        if($debug){$mensaje=array();}
        $nombreTabla=$this->tableName;
        $params=$this->parsePath($path,$ehObject,$shObject,$rhObject);
        if($params!=NULL){
            $tipo=$shObject->getType($params['id_structure']);
            if ($tipo=='node') {
                if($debug){$mensaje[]="Invalid type($tipo): $path. Function will return false";}
                $resultado= false;
            }else{
                $query="REPLACE INTO ".$nombreTabla." (id,id_structure,value)
                        VALUES (".$params['id'].",".$params['id_structure'].",'".$value."')";
                $result=DB::query($query);
                if($debug){$mensaje[]="Valid path: $path. Function will return $result.";}
                $resultado=$result;
            }
        }else {
            if($debug){$mensaje[]="Invalid path: $path. Function will return false";}
            $resultado=false;
        }
        if($debug){
            foreach($mensaje as $mens){
                trigger_error($mens,E_USER_NOTICE);
            }
        }
        return $resultado;
    }
    


     /**
      * It returns an array composed by each element of the path
      * @param string $path
      * @param ElementHandler $ehObject
      * @param StructHandler $shObject
      * @return array composed by each element of the path
      */
    public function parsePath($path,$ehObject,$shObject,$rhObject){
        $campos=explode($this->separador,substr($path,1));
        $elemento="";
        $nombreEstructura="";
        $tipos="";
        $elementoEncontrado=false;
        $finElementos=false;
        $contadorElementos=0;
        $salida=array();
        foreach($campos as $campo){
            $pos=strpos($campo,$this->separadorIds);
            if(!($pos===false)){
                //Viene un TIPO-ID
                $elemento=$elemento.$this->separador.$campo;
                $tipos=$tipos.$this->separadorIds.substr($campo,0,$pos);
                $contadorElementos++;
                $elementoEncontrado=true;
            }else if (($elementoEncontrado)&&(!$finElementos)){
                //Se terminaron los campos TIPO-ID/...
                if($contadorElementos==1){
                    //Elemento simple
                    $partido=explode($this->separadorIds,substr($elemento,1));
                    $salida['id']=$partido[1];
                    $salida['type']=$partido[0];
                    $nombreEstructura=$nombreEstructura.$this->separador.$partido[0].$this->separador.$campo;
                    if(!$ehObject->exists($salida['type'].$this->separadorIds.$salida['id'])){
                        return null;
                    }
                }
                else{
                    //Terminamos de encontrar un elemento compuesto.
                    $salida['id']=$rhObject->getId(substr($elemento,1));
                    if($salida['id']<0) {
                        return null;
                    }
                    $salida['type']=substr($tipos,1);
                    $nombreEstructura=$nombreEstructura.$this->separador.substr($tipos,1).$this->separador.$campo;
                }
                $finElementos=true;
            }else{
            //Todavia no hay elementos
            $nombreEstructura=$nombreEstructura.$this->separador.$campo;
            }
        }
        $idestructura=$shObject->getId($this->nombreRaiz.$nombreEstructura);
        if($idestructura<0){
            return null;
        }
        $salida['id_structure']=$idestructura;;
        return $salida;

    }


    /**
     * Function that deletes an atribute from the data table.
     * @param string $path
     * @return boolean true if a row has been deleted, false if any row has been deleted.
     */
    public function deleteValue($path,$ehObject,$shObject,$rhObject,$debug=false){
        $nombreTabla=$this->tableName;
        $params=$this->parsePath($path,$ehObject,$shObject,$rhObject);
        if($params!=NULL){
            $query="DELETE FROM ".$nombreTabla." WHERE id=".$params['id']." AND id_structure=".$params['id_structure'];
            $result=DB::query($query);
        }
        else $result=false;
       if($debug){
            if ($result){$mensaje="Value: $path Has been deleted.";}
            else{$mensaje="Value: $path Can not be deleted.";}
            trigger_error($mensaje,E_USER_NOTICE);
        }
        return $result;
    }


    /**
     * Function that deletes all data of the given id
     * @param integer $element_id
     * @param bool $debug for debug messages.
     * @return boolean true if any row has been deleted.
     */
    public function deleteValuesById($element_id,$debug=false){
        $nombreTabla=$this->tableName;
        if($element_id>0){
            $query="DELETE FROM ".$nombreTabla." WHERE id=".$element_id;
            $result=DB::query($query);
            if($debug){
                if ($result){$mensaje="All values of element [$element_id] Have been deleted. Function will return true.";}
                else{$mensaje="Element [$element_id] Has not any value or not exist. Function will return false.";}
            }
        }else {
            if($debug)$mensaje="Invalid element_id. Function will return false.";
            $result=false;
        }
        if($debug){trigger_error($mensaje,E_USER_NOTICE);}
        return $result;
    }
}
?>
